#include "sys.h"

#ifdef SYS_PLAT_WINDOWS
/**
 * @brief 获取当前时间
 */
void sys_time_curr (net_time_t * time) {
    // https://learn.microsoft.com/zh-cn/windows/win32/api/sysinfoapi/nf-sysinfoapi-gettickcount?redirectedfrom=MSDN
    *time = GetTickCount();     // 自系统启动以来已用过的毫秒数
}

/**
 * @brief 返回当前时间与传入的time之间时间差值, 调用完成之后，time被更新为当前时间
 *
 * 第一次调用时，返回的时间差值无效
 */
int sys_time_goes (net_time_t * pre) {
    // 获取当前时间
    net_time_t curr = GetTickCount();

    // 记录过去了多少毫秒
   int diff_ms = curr - *pre;

    // 记录下这次调用的时间
    *pre  = curr;
    return diff_ms;
}

sys_sem_t sys_sem_create(int init_count) {
    return CreateSemaphore(NULL, init_count, 0xFFFF, NULL);
}

void sys_sem_free(sys_sem_t sem) {
    CloseHandle(sem);
}

int sys_sem_wait(sys_sem_t sem, uint32_t tmo_ms) {
    DWORD tmo = (tmo_ms < 0) ? INFINITE : tmo_ms;
    DWORD  err = WaitForSingleObject(sem, tmo);
    if (err == WAIT_OBJECT_0) {
        mnet_printf("wait done\n");
        return 0;
    }

    if (err == WAIT_TIMEOUT) {
        return -4;
    }

    printf("wait error\n");
    return -1;
}

void sys_sem_notify(sys_sem_t sem) {
    ReleaseSemaphore(sem, 1, NULL);
}

/**
 * 创建线程互斥锁
 * @return 创建的互斥信号量
 */
sys_mutex_t sys_mutex_create(void) {
    sys_mutex_t mutex = CreateMutex(NULL, FALSE, NULL); // 初始不被占用
    if (mutex == NULL) {
        return SYS_MUTEX_INVALID;
    }
    return mutex;
}

/**
 * 释放互斥信号量
 * @param mutex
 */
void sys_mutex_free(sys_mutex_t locker) {
    ReleaseMutex(locker);
}

/**
 * 锁定线程互斥锁
 * @param mutex 待锁定的互斥信号量
 */
void sys_mutex_lock(sys_mutex_t locker) {
    WaitForSingleObject(locker, INFINITE);
}

/**
 * 释放线程互斥锁
 * @param mutex 待释放的互斥信号量
 */
void sys_mutex_unlock(sys_mutex_t locker) {
    ReleaseMutex(locker);
}

sys_thread_t sys_thread_create(void (*entry)(void * arg), void* arg) {
    return CreateThread(
        NULL,                           // SD
        0,                              // initial stack size
        (LPTHREAD_START_ROUTINE)entry,  // thread function
        arg,                            // thread argument
        0,                              // 创建后立即运行
        NULL                            // thread identifier
        );
}

sys_event_t sys_event_create(void *event_name) {
    return CreateEvent(
        NULL,               // default security attributes
        FALSE,              // manual-reset event
        FALSE,              // initial state is nonsignaled
        event_name          // object name
        );
}

int sys_event_wait(sys_event_t event_t, uint32_t ms) {
    DWORD tmo = (ms < 0) ? INFINITE : ms;
    DWORD err = WaitForSingleObject(
        event_t,
        tmo);
    switch (err) {
        case WAIT_OBJECT_0:
            // mnet_printf("wait success\n");
            return 0;
        case WAIT_TIMEOUT:
            // mnet_printf("wait timeout\n");
            return -4;
        default:
            // mnet_printf("wait error\n");
            return -1;
    }
}

void sys_event_notify(sys_event_t event_t) {
    SetEvent(event_t);
}

int sys_pipe_create(void *pipe_name, HANDLE *handle) {
    // 创建命名管道
    HANDLE pipe =
        CreateNamedPipe(
            pipe_name,                  // 管道名
            PIPE_ACCESS_DUPLEX,         // 双向访问
            PIPE_TYPE_MESSAGE |         // 访问模式
            PIPE_READMODE_MESSAGE |
            PIPE_WAIT,
            PIPE_UNLIMITED_INSTANCES,
            1024,                       // 输出缓冲区大小
            1024,                       // 输入缓冲区大小
            0,                          // 客户端超时时间
            NULL                        // 默认安全属性
            );
    if (pipe == INVALID_HANDLE_VALUE) {
        mnet_printf("creat pipe -1\n");
        return -1;
    }
    // if (!WaitNamedPipe(pipe_name, NMPWAIT_USE_DEFAULT_WAIT))
    // {
    //     mnet_printf("creat pipe -2\n");
    //     return -2;
    // }
    *handle = pipe;
    return 0;
}

int sys_wait_pipe_create(void *pipe_name) {
    return WaitNamedPipe(pipe_name, NMPWAIT_USE_DEFAULT_WAIT);
}

// 打开可用的命名管道 , 并与服务器端进程进行通信
HANDLE sys_open_pipe(void *pipe_name) {
    return CreateFile(pipe_name, GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, 0, NULL);
}

int sys_wait_client_connect(HANDLE pipe_name) {
    return ConnectNamedPipe(pipe_name, NULL);
}

void sys_pipe_read(HANDLE pipe_name, void *buffer, unsigned int size, void *r_size) {
    ReadFile(pipe_name, buffer, size, r_size, NULL);
}

void sys_pipe_write(HANDLE pipe_name, void *buffer, unsigned int size, void *w_size) {
    WriteFile(pipe_name, buffer, size, w_size, NULL);
}

// int sys_get_pipe_client_id(HANDLE pipe_name, void *id) {
//     return GetNamedPipeClientProcessId(pipe_name, id);
// }

int sys_pipe_write2(HANDLE pipe, char *msg, int len) {
    if (msg == NULL) {
        mnet_printf("null ptr in sys_pipe_write2\n");
        return -1;
    }
    PIPEMSG p_msg;
    int w_size;
    int remain_len = len;
    while (remain_len > 0) {
        int trans_len = (remain_len > 507) ? 507 : remain_len;
        p_msg.pip_stru.len = trans_len;
        p_msg.pip_stru.is_end = (remain_len > 507) ? 0 : 1;
        memcpy(p_msg.pip_stru.msg, msg, trans_len);
        sys_pipe_write(pipe, p_msg.pipe_msg, sizeof(PIPEMSG), &w_size);
        if (w_size != sizeof(int) + trans_len) {
            return -1;
        }
        remain_len -= trans_len;
        msg += trans_len;
    }
    return 0;
}

int sys_pipe_read2(HANDLE pipe, PIPEMSG *msg) {
    if (msg == NULL) {
        mnet_printf("null ptr in sys_pipe_read2\n");
        return -1;
    }
    int r_size;
    sys_pipe_read(pipe, &msg->pip_stru.len, 5, &r_size);

    sys_pipe_read(pipe, msg->pip_stru.msg, msg->pip_stru.len, &r_size);
    return 0;
}

/**
 * @brief 结束线程，目前只能结束自己
 */
void sys_thread_exit (int error) {
    ExitThread((DWORD)error);
}

sys_thread_t sys_thread_self (void) {
    return GetCurrentThread();
}

/**
 * @brief 简单的延时，以毫秒为单位
 */
void sys_sleep(int ms) {
    Sleep(ms);
}

void sys_plat_init(void) {
}

#endif